package prvydevj;

import org.basex.core.BaseXException;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * Created with IntelliJ IDEA.
 * User: marpies
 * Date: 5/3/13
 * Time: 10:35 PM
 * To change this template use File | Settings | File Templates.
 */
public class MainForm {
    private JTabbedPane mainPanel;
    private JTable records;
    private JTextField jmeno;
    private JTextField prijmeni;
    private JTextField ucetPart2;
    private JComboBox incomeBox;
    private JButton createBtn;
    private JTextField itemDescription;
    private JSpinner itemQuantity;
    private JSpinner itemPrice;
    private JTextField ucetPart1;
    private JTable items;
    private JTextField textFiel;
    private JComboBox ucetPart3;
    private JButton addItemButton;
    private JLabel fullPriceLabel;
    private JLabel transactionsCount;
    private JLabel transactionsIncome;
    private JLabel transactionsOutcome;
    private JLabel transactionsProfit;
    private JTextField adresa;
    private JTextField psc;
    private JTextField mesto;
    private JTextField ico;
    private JTextField dic;
    private JPanel dates;
    private JSpinner date1;
    private JSpinner date2;
    private JButton smazatPolozky;
    InvoiceManager manager = new InvoiceManager();
    DecimalFormat df;

    public MainForm() {
        df = new DecimalFormat();
        df.setMaximumFractionDigits(2);
        df.setMinimumFractionDigits(2);

        addItemButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (itemDescription.getText().isEmpty())
                {
                    JOptionPane.showMessageDialog(null,"Chybejici popis polozky.", e.getActionCommand(), JOptionPane.WARNING_MESSAGE);
                    return;
                }

                if (itemQuantity.getValue() == 0)
                {
                    JOptionPane.showMessageDialog(null,"Nulovy pocet polozek", e.getActionCommand(), JOptionPane.WARNING_MESSAGE);
                    return;
                }

                InvoiceItemTableModel invoiceModel = (InvoiceItemTableModel) items.getModel();
                invoiceModel.add( new InvoiceItem(itemDescription.getText(), (int)itemQuantity.getValue(), BigDecimal.valueOf((double)itemPrice.getValue())) );

                BigDecimal sum = BigDecimal.valueOf(0);

                for (int i =0, n = invoiceModel.getRowCount(); i< n; i++)
                  sum = sum.add( ((BigDecimal)invoiceModel.getValueAt(i, 2)).multiply(BigDecimal.valueOf((int) invoiceModel.getValueAt(i, 1))) );

                fullPriceLabel.setText(df.format(sum));

            }
        });
        createBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                InvoiceItemTableModel invoiceModel = (InvoiceItemTableModel) items.getModel();

                //validate inputs
                if (invoiceModel.getRecords().size() < 1)
                {
                    JOptionPane.showMessageDialog(null,"Faktura neobsahuje polozky.", e.getActionCommand(), JOptionPane.WARNING_MESSAGE);
                    return;
                }

                if (jmeno.getText().isEmpty() || prijmeni.getText().isEmpty() || ico.getText().isEmpty() || mesto.getText().isEmpty() || adresa.getText().isEmpty() || psc.getText().isEmpty())
                {
                    JOptionPane.showMessageDialog(null,"Zadejte udaje protistrany.", e.getActionCommand(), JOptionPane.WARNING_MESSAGE);
                    return;
                }

                String account_code = ((String)ucetPart3.getSelectedItem()).split(" ")[0];
                String account = ucetPart1.getText() + "-" + ucetPart2.getText() + "/" + account_code;
                Boolean income = incomeBox.getSelectedIndex() == 0;
                Transaction transaction = new Transaction(0, (Date)date1.getValue(), (Date)date2.getValue(), account, income);
                transaction.setOrganisation(jmeno.getText() + " " + prijmeni.getText(),  ico.getText(), dic.getText(), mesto.getText(), adresa.getText(), psc.getText());

                for ( InvoiceItem item : invoiceModel.getRecords())
                {
                    transaction.addItem(item);
                }

                manager.addTransaction(transaction);


                JOptionPane.showMessageDialog(null,"Faktura cislo " + transaction.getId() + " vytvorena.", e.getActionCommand(), JOptionPane.WARNING_MESSAGE);
             }
        });

        mainPanel.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                if (mainPanel.getSelectedIndex() == 0)
                {
                    loadTransactions();
                }
            }
        });
        smazatPolozky.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                InvoiceItemTableModel invoiceModel = (InvoiceItemTableModel) items.getModel();
                invoiceModel.clear();
                invoiceModel.fireTableDataChanged();
                fullPriceLabel.setText(df.format(0));
            }
        });
    }

    private void loadTransactions()
    {
        TransactionTableModel model = (TransactionTableModel) records.getModel();
        model.clear();
        List<Transaction> transactions = manager.getAllTransactions();
        BigDecimal income = BigDecimal.valueOf(0);
        BigDecimal outcome = BigDecimal.valueOf(0);

        for ( Transaction transaction : transactions)
        {
            model.add(transaction);
            if (transaction.getPrijem())
                income = income.add(transaction.getCastka());
            else
                outcome = outcome.add(transaction.getCastka());
        }

        transactionsCount.setText("Počet transakcí: " + transactions.size());
        transactionsIncome.setText("Příjem: " + df.format(income));
        transactionsOutcome.setText("Výdej: " + df.format(outcome));
        transactionsProfit.setText("Zisk: " + df.format(income.subtract(outcome)) );

        date1.setLocale(new Locale("cs", "cz"));
        date2.setLocale(new Locale("cs", "cz"));

        Calendar calendar = Calendar.getInstance();
        Date initDate = calendar.getTime();
        calendar.add(Calendar.YEAR, -5);
        Date earliestDate = calendar.getTime();
        calendar.add(Calendar.YEAR, 10);
        Date latestDate = calendar.getTime();

        date1.setModel(new SpinnerDateModel(initDate, earliestDate, latestDate, Calendar.MONTH));
        date1.setEditor(new JSpinner.DateEditor(date1, "dd MM yyyy"));
        date2.setModel(new SpinnerDateModel(initDate, earliestDate, latestDate, Calendar.MONTH));
        date2.setEditor(new JSpinner.DateEditor(date2, "dd MM yyyy"));
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                // main window
                final MainForm form = new MainForm();
                JFrame frame = new JFrame("Evidence");

                frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                frame.setContentPane(form.mainPanel);
                frame.setPreferredSize(new Dimension(720, 520));
                frame.pack();
                frame.setVisible(true);

                try {
                    form.manager.Connect("resources/database.xml");
                } catch (BaseXException | DatatypeConfigurationException | ParserConfigurationException e) {
                    System.out.println(e.getMessage());
                    JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
                    System.exit(1);
                }

                TransactionTableModel model = new TransactionTableModel();
                form.records.setModel(model);

                AbstractAction action = new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        TransactionTableModel model = (TransactionTableModel) form.records.getModel();
                        int index = form.records.getSelectedRow();
                        if (index >= 0)
                        {
                            Transaction transaction = model.getRecords().get(index);
                            InvoiceForm.Show(form.manager, transaction);
                        }
                    }
                };

                form.records.getColumn("").setCellRenderer(new ButtonRenderer());
                form.records.getColumn("").setCellEditor(new ButtonEditor(action));
                form.records.getColumn("Částka (CZK)").setCellRenderer( new ColorCellRenderer() );
                form.loadTransactions();

                InvoiceItemTableModel invoiceModel = new InvoiceItemTableModel();
                form.items.setModel(invoiceModel);

                JMenu soubor = new JMenu("Soubor");
                JMenuItem ukoncit = new JMenuItem("Ukončit");
                ukoncit.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.exit(1);
                    }
                });
                soubor.add(ukoncit);

                JMenu osobni = new JMenu("Osobní udaje");
                JMenuItem upravit = new JMenuItem("Upravit osobní udaje");

                upravit.addActionListener(new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                            EditDetailsForm.Show(form.manager);
                    }
                });
                osobni.add(upravit);

                JMenu fakturace = new JMenu("Fakturace");
                JMenuItem novaFaktura = new JMenuItem("Přidat novou fakturu");
                fakturace.add(novaFaktura);

                JMenu napoveda = new JMenu("Nápověda");
                JMenuItem about = new JMenuItem("O Programu");
                napoveda.add(about);

                about.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JOptionPane.showMessageDialog(null,"Desktopová aplikace pro evidenci příjmů a výdajů pro OSVČ.\nhttps://code.google.com/p/prvydevj/", e.getActionCommand(), JOptionPane.INFORMATION_MESSAGE);
                    }
                });

                novaFaktura.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        form.mainPanel.setSelectedIndex(1);
                    }
                });


                // Add JMenu bar
                JMenuBar menuBar = new JMenuBar();
                menuBar.add(soubor);
                menuBar.add(osobni);
                menuBar.add(fakturace);
                menuBar.add(napoveda);

                frame.setJMenuBar(menuBar);
                frame.setLocation( 200, 200 );
            }
        });
    }

    private static JMenuItem makeMenuItem(String name) {
        JMenuItem m = new JMenuItem(name);
        return m;
    }

    private void createUIComponents() {
        // TODO: place custom component creation code here

        double min = 0;
        double value = 0;
        double max = Double.MAX_VALUE;
        double stepSize = 1;
        SpinnerNumberModel model = new SpinnerNumberModel(value, min, max, stepSize);
        itemPrice = new JSpinner(model);

        JSpinner.NumberEditor editor = (JSpinner.NumberEditor)itemPrice.getEditor();
        DecimalFormat format = editor.getFormat();
        format.setMinimumFractionDigits(2);
        format.setMaximumFractionDigits(4);
    }
}

class ButtonRenderer extends JButton implements TableCellRenderer {
    public ButtonRenderer() {
        setOpaque(true);
    }
    public Component getTableCellRendererComponent(JTable table, Object value,
                                                   boolean isSelected, boolean hasFocus, int row, int column) {
        setText((value == null) ? "" : value.toString());
        return this;
    }
}

class ButtonEditor extends AbstractCellEditor implements TableCellEditor {
    private final JButton button;

    public ButtonEditor(AbstractAction action) {
        button = new JButton(action);
        button.setFocusable(false);
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,      boolean isSelected, int row, int column) {
        button.setText(value.toString());
        return button;
    }

    @Override
    public Object getCellEditorValue() {
        return null;
    }
}

class ColorCellRenderer extends DefaultTableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
                                                   boolean isSelected, boolean hasFocus, int row, int column) {

        super.getTableCellRendererComponent(table, value, isSelected,
                hasFocus, row, column);
        BigDecimal val = new BigDecimal( value.toString() );
        if( val.compareTo( BigDecimal.ZERO ) > 0 ) {
            setForeground(new Color(29, 152, 0));
        } else {
            setForeground(Color.RED);
        }
        return this;
    }

}